//---------------------------------------------------------------------------

#include "vcl_stl.h"
#pragma hdrstop

#include <stdlib.h>

#include "h_base.h"
#include "h_xml.h"
#include "h_global.h"
using namespace h_base;
using namespace h_xml;

#include "h_designcontrol.h"

#include "h_stage.h"
#include "h_g.h"
#include "h_portal.h"
#include "h_lic.h"
#include "h_server.h"
#include "reinit.hpp"
#include "h_i18n.h"
#include "h_progressbar.h"
#include "t_mainform.h"
#include "t_dummyform.h"
#include "t_aboutform.h"
#include "t_listform.h"
#include "t_batlistform.h"
#include "t_ganttform.h"
#include "t_concurrencyform.h"
#include "t_messageform.h"
//---------------------------------------------------------------------------

namespace h_g
{

static map<UTF8String, HStage*> FStageRegister;
static UTF8String LogFileName;
static TCriticalSection *OutlineCs = NULL;
static TCriticalSection *DebugCs = NULL;
static UTF8String WindowStyle;

int LicQty = 0;
UTF8String BaseDir;
UTF8String BinDir;
int Interval;
UTF8String WhistleFile;
UTF8String EndSoundFile;
bool Copyright;
bool InitFail;
bool ExitFlag;
bool DebugFlag;
bool AlarmEnableFlag;
bool RememberPasswordFlag;
UTF8String FadingPeriod;
char JobNameDelimiter[2];
vector<string> SpecialDateList;
vector<string> ExcludeList;
UTF8String MainformCaption;

TColor IconSelectedColor;
TColor IconRunningColor;
TColor IconSuccessColor;
TColor IconFailedColor;
TColor IconSkippedColor;
TColor IconUnknownColor;
TColor IconWaitingColor;
TColor IconPausedColor;
TColor IconAlarmColor;
TColor LineColor;
TColor LineShadowColor;
TColor TextColor;
TColor TabTextColor;

Graphics::TBitmap *Background = NULL;
Graphics::TBitmap *CustLogo = NULL;
Graphics::TBitmap *Homepage = NULL;
Graphics::TBitmap *ToolbarLogo = NULL;
Graphics::TBitmap *Logo = NULL;
vector<Graphics::TBitmap*> BitmapConnector;
vector<Graphics::TBitmap*> BitmapArrow;

bool HomepageLargeIcon = false;
bool CustLogoFlag = true;

vector<TColor> IconTextColors;

vector<Graphics::TBitmap*> BitmapBatchBg1;
vector<Graphics::TBitmap*> BitmapBatchBg2;
vector<Graphics::TBitmap*> BitmapBatchBg3;
vector<Graphics::TBitmap*> BitmapJobBg1;
vector<Graphics::TBitmap*> BitmapJobBg2;
vector<Graphics::TBitmap*> BitmapJobBg3;
vector<Graphics::TBitmap*> BitmapExternJobBg1;
vector<Graphics::TBitmap*> BitmapExternJobBg2;
vector<Graphics::TBitmap*> BitmapExternJobBg3;
vector<Graphics::TBitmap*> BitmapGroupBg1;
vector<Graphics::TBitmap*> BitmapGroupBg2;
vector<Graphics::TBitmap*> BitmapGroupBg3;
vector<Graphics::TBitmap*> BitmapFwBg;
vector<Graphics::TBitmap*> BitmapServerBg;
vector<Graphics::TBitmap*> BitmapTimeBg;

vector<Graphics::TBitmap*> BitmapServer;
vector<Graphics::TBitmap*> BitmapServerBg2;

LCID LocaleID;
UTF8String ClientCodeSet;

int ExpireDate;

static unsigned char DavinciCode[1024];

static bool LoadDavinciFlag = false;
static void __fastcall LoadDavinciCode(unsigned char *Buf);
static void __fastcall SaveDavinciCode();
static void Davinci(void *Parm, int ParmLen);

static int __fastcall ToGray(TColor Color)
{
   unsigned int Red;
   unsigned int Green;
   unsigned int Blue;

   Red = Color & 0x000000ff;
   Green = ( Color & 0x0000ff00 ) >> 8;
   Blue = ( Color & 0x00ff0000 ) >> 16;

   return ( Red * 30 + Green * 59 + Blue * 11 ) / 100 % 256;
}

static unsigned char __fastcall ToGray(const unsigned char SrcBuf[3])
{
   return ( (unsigned int)SrcBuf[2] * 30 + (unsigned int)SrcBuf[1] * 59 +
      (unsigned int)SrcBuf[0] * 11 ) / 100 % 256;
}

static TColor __fastcall CalcColor(TColor Color, int Gray)
{
   unsigned int Red;
   unsigned int Green;
   unsigned int Blue;

   Red = Color & 0x000000ff;
   Green = ( Color & 0x0000ff00 ) >> 8;
   Blue = ( Color & 0x00ff0000 ) >> 16;

   Red = Red * Gray / 256;
   Green = Green * Gray / 256;
   Blue = Blue * Gray / 256;
   return TColor(Red | ( Green << 8 ) | ( Blue << 16 ));
}

static void __fastcall CalcColor(const unsigned char BaseColorBuf[3],
   const unsigned char SrcBuf[3], unsigned char DesBuf[3])
{
   unsigned int Gray = SrcBuf[0];

   DesBuf[2] = BaseColorBuf[2] * Gray / 256;
   DesBuf[1] = BaseColorBuf[1] * Gray / 256;
   DesBuf[0] = BaseColorBuf[0] * Gray / 256;
}

static TColor StrToColor(const char *s)
{
   unsigned int Red;
   unsigned int Green;
   unsigned int Blue;
   int Pos = 0;
   char w[80 + 1];

   Pos += ReadWord(s + Pos, w, ", ", 80);
   Red = StrToInt(w);
   Pos += ReadWord(s + Pos, w, ", ", 80);

   if ( strcmp(w, ",") != 0 )
   {
      return clBlack;
   }

   Pos += ReadWord(s + Pos, w, ", ", 80);
   Green = StrToInt(w);
   Pos += ReadWord(s + Pos, w, ", ", 80);

   if ( strcmp(w, ",") != 0 )
   {
      return clBlack;
   }

   Pos += ReadWord(s + Pos, w, ", ", 80);
   Blue = StrToInt(w);
   return TColor(Red | ( Green << 8 ) | ( Blue << 16 ));
}

static bool __fastcall LoadColors(const UTF8String &Skin)
{
   UTF8String FileName = BaseDir + "skin\\" + Skin + "\\colors.xml";

   if ( !FileExist(FileName) )
   {
      FileName = BaseDir + "skin\\" + "default" + "\\colors.xml";
   }

   HXmlTree Colors;

   if ( !Colors.LoadFromFile(FileName.c_str()) )
   {
      char Err[200 + 1];
      snprintf(Err, 200, h_g::I18nString("h_g:LOAD_FAIL"),
         "colors.xml", Colors.GetErrorString().c_str());
      h_g::ShowMessage(UTF8String(Err));
      return false;
   }

   IconSelectedColor = StrToColor(
      Colors.GetValue("ICON_SELECTED_COLOR").c_str());
   IconRunningColor = StrToColor(
      Colors.GetValue("ICON_RUNNING_COLOR").c_str());
   IconSuccessColor = StrToColor(
      Colors.GetValue("ICON_SUCCESS_COLOR").c_str());
   IconFailedColor = StrToColor(
      Colors.GetValue("ICON_FAILED_COLOR").c_str());
   IconSkippedColor = StrToColor(
      Colors.GetValue("ICON_SKIPPED_COLOR").c_str());
   IconUnknownColor = StrToColor(
      Colors.GetValue("ICON_UNKNOWN_COLOR").c_str());
   IconWaitingColor = StrToColor(
      Colors.GetValue("ICON_WAITING_COLOR").c_str());
   IconPausedColor = IconSkippedColor;
   IconAlarmColor = IconFailedColor;
   LineColor = StrToColor(
      Colors.GetValue("LINE_COLOR").c_str());
   LineShadowColor = StrToColor(
      Colors.GetValue("LINE_SHADOW_COLOR").c_str());
   TextColor = StrToColor(
      Colors.GetValue("TEXT_COLOR").c_str());

   IconTextColors.clear();

   for ( int i = 0; i < 10; i++ )
   {
      IconTextColors.push_back(clBlack);
   }

   IconTextColors[itNormal] = StrToColor(
      Colors.GetValue("ICON_NORMAL_TEXT_COLOR").c_str());
   IconTextColors[itSelected] = StrToColor(
      Colors.GetValue("ICON_SELECTED_TEXT_COLOR").c_str());
   IconTextColors[itRunning] = StrToColor(
      Colors.GetValue("ICON_RUNNING_TEXT_COLOR").c_str());
   IconTextColors[itSuccess] = StrToColor(
      Colors.GetValue("ICON_SUCCESS_TEXT_COLOR").c_str());
   IconTextColors[itFailed] = StrToColor(
      Colors.GetValue("ICON_FAILED_TEXT_COLOR").c_str());
   IconTextColors[itSkipped] = StrToColor(
      Colors.GetValue("ICON_SKIPPED_TEXT_COLOR").c_str());
   IconTextColors[itUnknown] = StrToColor(
      Colors.GetValue("ICON_UNKNOWN_TEXT_COLOR").c_str());
   IconTextColors[itWaiting] = StrToColor(
      Colors.GetValue("ICON_WAITING_TEXT_COLOR").c_str());
   IconTextColors[itPaused] = IconTextColors[itSkipped];
   IconTextColors[itAlarm] = IconTextColors[itFailed];

   HomepageLargeIcon = ( Colors.GetValueUpper("HOMEPAGE_LARGE_ICON") == "TRUE" );
   CustLogoFlag = ( Colors.GetValueUpper("CUST_LOGO") != "FALSE" );
   WindowStyle = Colors.GetValue("WINDOW_STYLE", "Windows").c_str();
   return true;
}

static void __fastcall LoadIconBitmap(vector<Graphics::TBitmap*> &BitmapVec,
   const UTF8String &Skin, const UTF8String &IconName)
{
   TColor IconColors[10];

   IconColors[itSelected] = IconSelectedColor;
   IconColors[itRunning] = IconRunningColor;
   IconColors[itSuccess] = IconSuccessColor;
   IconColors[itFailed] = IconFailedColor;
   IconColors[itSkipped] = IconSkippedColor;
   IconColors[itUnknown] = IconUnknownColor;
   IconColors[itWaiting] = IconWaitingColor;
   IconColors[itPaused] = IconPausedColor;
   IconColors[itAlarm] = IconAlarmColor;

   Graphics::TBitmap *BaseBitmap = new Graphics::TBitmap();
   UTF8String FileName = BaseDir + "skin\\" + Skin + "\\" + IconName + ".bmp";

   if ( !FileExist(FileName) )
   {
      FileName = BaseDir + "skin\\" + "default" + "\\" + IconName + ".bmp";
   }

   BaseBitmap->PixelFormat = pf24bit;
   BaseBitmap->LoadFromFile(FileName);
   TColor TransparentColor = BaseBitmap->Canvas->Pixels[0][0];
   BaseBitmap->TransparentMode = tmFixed;
   BaseBitmap->TransparentColor = TransparentColor;
   BaseBitmap->Transparent = true;
   BitmapVec.push_back(BaseBitmap);

   unsigned char TransparentColorBuf[3];

   TransparentColorBuf[2] = TransparentColor & 0x000000ff;
   TransparentColorBuf[1] = ( TransparentColor & 0x0000ff00 ) >> 8;
   TransparentColorBuf[0] = ( TransparentColor & 0x00ff0000 ) >> 16;

   Graphics::TBitmap *GrayBitmap = new Graphics::TBitmap();

   GrayBitmap->PixelFormat = pf24bit;
   GrayBitmap->Width = BaseBitmap->Width;
   GrayBitmap->Height = BaseBitmap->Height;

   for ( int y = 0; y < GrayBitmap->Height; y++ )
   {
      unsigned char *BaseBuf = (unsigned char *)BaseBitmap->ScanLine[y];
      unsigned char *Buf = (unsigned char *)GrayBitmap->ScanLine[y];
      for ( int x = 0; x < GrayBitmap->Width; x++, BaseBuf += 3, Buf += 3 )
      {
         if ( memcmp(BaseBuf, TransparentColorBuf, 3) == 0 )
         {
            memcpy(Buf, TransparentColorBuf, 3);
         }
         else
         {
            *Buf = ToGray(BaseBuf);
         }
      }
   }

   for ( int i = 1; i < sizeof(IconColors) / sizeof(TColor); i++ )
   {
      Graphics::TBitmap *Bitmap = new Graphics::TBitmap();
      Bitmap->PixelFormat = pf24bit;
      Bitmap->Width = BaseBitmap->Width;
      Bitmap->Height = BaseBitmap->Height;
      Bitmap->TransparentMode = tmFixed;
      Bitmap->TransparentColor = TransparentColor;
      Bitmap->Transparent = true;
      TColor BaseColor = IconColors[i];
      unsigned char BaseColorBuf[3];
      BaseColorBuf[2] = BaseColor & 0x000000ff;
      BaseColorBuf[1] = ( BaseColor & 0x0000ff00 ) >> 8;
      BaseColorBuf[0] = ( BaseColor & 0x00ff0000 ) >> 16;
      for ( int y = 0; y < GrayBitmap->Height; y++ )
      {
         unsigned char *BaseBuf = (unsigned char *)GrayBitmap->ScanLine[y];
         unsigned char *Buf = (unsigned char *)Bitmap->ScanLine[y];
         for ( int x = 0; x < GrayBitmap->Width; x++, BaseBuf += 3, Buf += 3 )
         {
            if ( memcmp(BaseBuf, TransparentColorBuf, 3) == 0 )
            {
               memcpy(Buf, TransparentColorBuf, 3);
            }
            else
            {
               CalcColor(BaseColorBuf, BaseBuf, Buf);
            }
         }
      }
      BitmapVec.push_back(Bitmap);
   }

   delete GrayBitmap;
}

static void __fastcall SplitBitmap(const vector<Graphics::TBitmap*> &BitmapVec,
   vector<Graphics::TBitmap*> &BitmapVec1, vector<Graphics::TBitmap*> &BitmapVec2,
   vector<Graphics::TBitmap*> &BitmapVec3)
{
   BitmapVec1.clear();
   BitmapVec2.clear();
   BitmapVec3.clear();

   for ( int i = 0; i < BitmapVec.size(); i++ )
   {
      Graphics::TBitmap *BaseBitmap = BitmapVec[i];
      TColor TransparentColor = BaseBitmap->TransparentColor;
      Graphics::TBitmap *Bitmap1 = new Graphics::TBitmap();
      Bitmap1->PixelFormat = pf24bit;
      Bitmap1->Width = BaseBitmap->Width / 3;
      Bitmap1->Height = BaseBitmap->Height;
      Bitmap1->TransparentMode = tmFixed;
      Bitmap1->TransparentColor = TransparentColor;
      Bitmap1->Transparent = true;
      Graphics::TBitmap *Bitmap2 = new Graphics::TBitmap();
      Bitmap2->PixelFormat = pf24bit;
      Bitmap2->Width = BaseBitmap->Width / 3;
      Bitmap2->Height = BaseBitmap->Height;
      Bitmap2->TransparentMode = tmFixed;
      Bitmap2->TransparentColor = TransparentColor;
      Bitmap2->Transparent = true;
      Graphics::TBitmap *Bitmap3 = new Graphics::TBitmap();
      Bitmap3->PixelFormat = pf24bit;
      Bitmap3->Width = BaseBitmap->Width / 3;
      Bitmap3->Height = BaseBitmap->Height;
      Bitmap3->TransparentMode = tmFixed;
      Bitmap3->TransparentColor = TransparentColor;
      Bitmap3->Transparent = true;
      for ( int y = 0; y < BaseBitmap->Height; y++ )
      {
         unsigned char *BaseBuf = (unsigned char *)BaseBitmap->ScanLine[y];
         unsigned char *Buf1 = (unsigned char *)Bitmap1->ScanLine[y];
         unsigned char *Buf2 = (unsigned char *)Bitmap2->ScanLine[y];
         unsigned char *Buf3 = (unsigned char *)Bitmap3->ScanLine[y];
         for ( int x = 0; x < BaseBitmap->Width / 3; x++ )
         {
            memcpy(Buf1 + x * 3, BaseBuf + x * 3, 3);
            memcpy(Buf2 + x * 3, BaseBuf + ( x + BaseBitmap->Width / 3 ) * 3, 3);
            memcpy(Buf3 + x * 3, BaseBuf + ( x + BaseBitmap->Width / 3 * 2 ) * 3, 3);
         }
      }
      BitmapVec1.push_back(Bitmap1);
      BitmapVec2.push_back(Bitmap2);
      BitmapVec3.push_back(Bitmap3);
   }
}

static void __fastcall FreeBitmaps(vector<Graphics::TBitmap*> &BitmapVec)
{
   for ( int i = 0; i < BitmapVec.size(); i++ )
   {
      delete BitmapVec[i];
   }

   BitmapVec.clear();
}

static void __fastcall LoadArrowBitmap(const UTF8String &Skin)
{
   Graphics::TBitmap *DownArrow = new Graphics::TBitmap();
   UTF8String FileName = BaseDir + "skin\\" + Skin + "\\arrow.bmp";

   if ( !FileExist(FileName) )
   {
      FileName = BaseDir + "skin\\" + "default" + "\\arrow.bmp";
   }

   DownArrow->LoadFromFile(FileName);
   TColor TransparentColor = DownArrow->Canvas->Pixels[0][0];
   DownArrow->TransparentMode = tmFixed;
   DownArrow->TransparentColor = TransparentColor;
   DownArrow->Transparent = true;
   BitmapArrow.push_back(DownArrow);

   Graphics::TBitmap *RightArrow = new Graphics::TBitmap();
   RightArrow->Width = DownArrow->Height;
   RightArrow->Height = DownArrow->Width;
   RightArrow->TransparentMode = tmFixed;
   RightArrow->TransparentColor = TransparentColor;
   RightArrow->Transparent = true;

   for ( int y = 0; y < DownArrow->Height; y++ )
   {
      for ( int x = 0; x < DownArrow->Width; x++ )
      {
         RightArrow->Canvas->Pixels[y][x] = DownArrow->Canvas->Pixels[x][y];
      }
   }

   BitmapArrow.push_back(RightArrow);

   Graphics::TBitmap *UpArrow = new Graphics::TBitmap();
   UpArrow->Width = DownArrow->Width;
   UpArrow->Height = DownArrow->Height;
   UpArrow->TransparentMode = tmFixed;
   UpArrow->TransparentColor = TransparentColor;
   UpArrow->Transparent = true;

   for ( int y = 0; y < DownArrow->Height; y++ )
   {
      for ( int x = 0; x < DownArrow->Width; x++ )
      {
         UpArrow->Canvas->Pixels[x][DownArrow->Height - 1 - y] =
            DownArrow->Canvas->Pixels[x][y];
      }
   }

   BitmapArrow.push_back(UpArrow);

   Graphics::TBitmap *LeftArrow = new Graphics::TBitmap();
   LeftArrow->Width = DownArrow->Height;
   LeftArrow->Height = DownArrow->Width;
   LeftArrow->TransparentMode = tmFixed;
   LeftArrow->TransparentColor = TransparentColor;
   LeftArrow->Transparent = true;

   for ( int y = 0; y < DownArrow->Height; y++ )
   {
      for ( int x = 0; x < DownArrow->Width; x++ )
      {
         LeftArrow->Canvas->Pixels[DownArrow->Height - 1 - y][x] =
            DownArrow->Canvas->Pixels[x][y];
      }
   }

   BitmapArrow.push_back(LeftArrow);
}

static void LoadButtonIcon(const UTF8String &Skin,
   int Index, const UTF8String &Name)
{
   Graphics::TBitmap *ButtonBitmap = new Graphics::TBitmap();
   Graphics::TBitmap *MaskBitmap = new Graphics::TBitmap();
   UTF8String FileName = BaseDir + "skin\\" + Skin + "\\button_" + Name + ".bmp";

   if ( !FileExist(FileName) )
   {
      FileName = BaseDir + "skin\\" + "default" + "\\button_" + Name + ".bmp";
   }

   ButtonBitmap->LoadFromFile(FileName);
   MaskBitmap->Assign(ButtonBitmap);
   MaskBitmap->Mask(ButtonBitmap->Canvas->Pixels[0][0]);
   MainForm->ImageList1->Replace(Index, ButtonBitmap, MaskBitmap);
   delete ButtonBitmap;
   delete MaskBitmap;
}

static void __fastcall LoadSkin(const UTF8String &Skin)
{
   Background = new Graphics::TBitmap();
   Homepage = new Graphics::TBitmap();
   UTF8String FileName;

   FileName = BaseDir + "skin\\" + Skin + "\\background.bmp";

   if ( !FileExist(FileName) )
   {
      FileName = BaseDir + "skin\\" + "default" + "\\background.bmp";
   }

   Background->LoadFromFile(FileName);
   FileName = BaseDir + "skin\\" + Skin + "\\homepage.bmp";

   if ( !FileExist(FileName) )
   {
      FileName = BaseDir + "skin\\" + Skin + "\\background.bmp";
   }

   if ( !FileExist(FileName) )
   {
      FileName = BaseDir + "skin\\" + "default" + "\\background.bmp";
   }

   Homepage->LoadFromFile(FileName);

   LoadColors(Skin);

   if ( CustLogoFlag )
   {
      FileName = BaseDir + "skin\\" + Skin + "\\cust_logo.bmp";
      if ( !FileExist(FileName) )
      {
         FileName = BaseDir + "skin\\" + "default" + "\\cust_logo.bmp";
      }
      if ( FileExist(FileName) )
      {
         CustLogo = new Graphics::TBitmap();
         CustLogo->LoadFromFile(FileName);
         TColor TransparentColor = CustLogo->Canvas->Pixels[0][0];
         CustLogo->TransparentMode = tmFixed;
         CustLogo->TransparentColor = TransparentColor;
         CustLogo->Transparent = true;
      }
   }

   LoadIconBitmap(BitmapConnector, Skin, "connector");
   LoadArrowBitmap(Skin);

   LoadIconBitmap(BitmapFwBg, Skin, "fw_bg");
   LoadIconBitmap(BitmapTimeBg, Skin, "time_bg");

   {
      vector<Graphics::TBitmap*> BitmapExternJobBg;
      LoadIconBitmap(BitmapExternJobBg, Skin, "extern_job_bg");
      SplitBitmap(BitmapExternJobBg, BitmapExternJobBg1, BitmapExternJobBg2, BitmapExternJobBg3);
      FreeBitmaps(BitmapExternJobBg);
   }

   {
      vector<Graphics::TBitmap*> BitmapGroupBg;
      LoadIconBitmap(BitmapGroupBg, Skin, "group_bg");
      SplitBitmap(BitmapGroupBg, BitmapGroupBg1, BitmapGroupBg2, BitmapGroupBg3);
      FreeBitmaps(BitmapGroupBg);
   }

   {
      vector<Graphics::TBitmap*> BitmapJobBg;
      LoadIconBitmap(BitmapJobBg, Skin, "job_bg");
      SplitBitmap(BitmapJobBg, BitmapJobBg1, BitmapJobBg2, BitmapJobBg3);
      FreeBitmaps(BitmapJobBg);
   }

   {
      vector<Graphics::TBitmap*> BitmapBatchBg;
      LoadIconBitmap(BitmapBatchBg, Skin, "batch_bg");
      SplitBitmap(BitmapBatchBg, BitmapBatchBg1, BitmapBatchBg2, BitmapBatchBg3);
      FreeBitmaps(BitmapBatchBg);
   }

   LoadIconBitmap(BitmapServerBg, Skin, "server_bg");

   if ( HomepageLargeIcon )
   {
      LoadIconBitmap(BitmapServer, Skin, "server");
      LoadIconBitmap(BitmapServerBg2, Skin, "server_bg2");
   }

   LoadButtonIcon(Skin, 0, "refresh");
   LoadButtonIcon(Skin, 1, "home");
   LoadButtonIcon(Skin, 2, "up");
   LoadButtonIcon(Skin, 3, "list");
   TStyleManager::TrySetStyle(WindowStyle);
}

static void __fastcall FreeSkin()
{
   delete Background;
   delete Homepage;

   if ( CustLogo != NULL )
   {
      delete CustLogo;
      CustLogo = NULL;
   }

   FreeBitmaps(BitmapConnector);
   FreeBitmaps(BitmapArrow);
   FreeBitmaps(BitmapFwBg);
   FreeBitmaps(BitmapExternJobBg1);
   FreeBitmaps(BitmapExternJobBg2);
   FreeBitmaps(BitmapExternJobBg3);
   FreeBitmaps(BitmapGroupBg1);
   FreeBitmaps(BitmapGroupBg2);
   FreeBitmaps(BitmapGroupBg3);
   FreeBitmaps(BitmapJobBg1);
   FreeBitmaps(BitmapJobBg2);
   FreeBitmaps(BitmapJobBg3);
   FreeBitmaps(BitmapServerBg);

   if ( HomepageLargeIcon )
   {
      FreeBitmaps(BitmapServer);
      FreeBitmaps(BitmapServerBg2);
   }
}


void __fastcall Init(void)
{
   UTF8String TmpStr;

   InitFail = true;
   ExitFlag = false;
   DebugFlag = false;
   strcpy(JobNameDelimiter, ":");
   SetLogFileName("debug.log");
   HComm::Init();
   OutlineCs = new TCriticalSection();
   DebugCs = new TCriticalSection();

   randomize();
   BinDir = ExtractFilePath(Application->ExeName);
   TmpStr = ExtractFilePath(ExcludeTrailingBackslash(BinDir));

   if( TmpStr == "" )
      BaseDir = BinDir;
   else
      BaseDir = TmpStr;

   HXmlTree Config;
   int PortalColQty;

   if ( !Config.LoadFromFile((BinDir + "simbat.cfg").c_str()) )
   {
      char Err[200 + 1];
      snprintf(Err, 200, "Load %s fail, %s",
         "simbat.cfg", Config.GetErrorString().c_str());
      h_g::ShowMessage(UTF8String(Err));
      return;
   }

   Config.SaveToFile((BinDir + "simbat_cfg.bak").c_str());
   UTF8String Skin;
   UTF8String Locale;
   HXmlTree *Cfg = Config.ForceGetChild("COMMON");
   Skin = Cfg->GetValue("SKIN", "DEFAULT").c_str();
   Locale = Cfg->GetValue("LOCALE", "").c_str();
   Copyright = Cfg->GetValueUpper("COPYRIGHT", "TRUE") == "TRUE";
   DebugFlag = Cfg->GetValueUpper("DEBUG") == "TRUE";
   AlarmEnableFlag = Cfg->GetValueUpper("ALARM_ENABLE", "TRUE") == "TRUE";
   RememberPasswordFlag = Cfg->GetValueUpper("REMEMBER_PASSWORD") == "TRUE";
   FadingPeriod = Cfg->GetValue("FADING_PERIOD").c_str();

   Cfg = Config.ForceGetChild("DESIGNER");
   Cfg->GetValues("SPECIAL_DATE_LIST", SpecialDateList);

   {
      Cfg = Config.ForceGetChild("MONITOR");
      Cfg->GetValues("EXCLUDE_LIST", ExcludeList);
   }

   h_g::WriteLog("================================================");

   int I18nIdx = 0;

   if ( Locale == "CHS" )
   {
      LocaleID = ( SUBLANG_CHINESE_SIMPLIFIED << 10 ) | LANG_CHINESE;
      I18nIdx = 2;
   }
   else if ( Locale == "ZHH" )
   {
      LocaleID = ( SUBLANG_CHINESE_HONGKONG << 10 ) | LANG_CHINESE;
      I18nIdx = 3;
   }
   else if ( Locale == "ENU" )
   {
      LocaleID = ( SUBLANG_ENGLISH_US << 10 ) | LANG_ENGLISH;
      I18nIdx = 1;
   }
   else
   {
      Locale = "";
      LocaleID = GetSystemDefaultLCID();
      if ( LocaleID == ( ( SUBLANG_CHINESE_SIMPLIFIED << 10 ) | LANG_CHINESE ) )
      {
         I18nIdx = 2;
      }
      else if ( LocaleID == ( ( SUBLANG_CHINESE_HONGKONG << 10 ) | LANG_CHINESE ) )
      {
         I18nIdx = 3;
      }
      else
      {
         I18nIdx = 1;
      }
   }

   I18nInit(I18nIdx);
   LoadSkin(Skin);

   if ( Locale != "" )
   {
      if ( LoadNewResourceModule(LocaleID) )
      {
         ReinitializeForms();
      }
   }

   {
      UTF8String LicUser;
      UTF8String ExpireDateStr;
      UTF8String LicProject;
      UTF8String LicFileName = BinDir + "simbat.lic";
      FILE *f = _wfopen(UnicodeString(LicFileName).c_str(), L"rb");
      if ( f == NULL )
      {
         h_g::ShowMessage(UTF8String(h_g::I18nString("h_g:LICENSE_NOT_FOUND")));
         return;
      }
      unsigned char Buf[LIC_BUF_LEN];
      fread(Buf, LIC_BUF_LEN, 1, f);
      fclose(f);
      LoadDavinciCode(Buf);
      if ( !GetLic(Buf, LicUser, ExpireDate, LicQty, LicProject) )
      {
         h_g::ShowMessage(UTF8String(h_g::I18nString("h_g:LICENSE_FILE_DAMAGED")));
         return;
      }
      if ( ExpireDate != 0 )
      {
         int ExpireYear = ExpireDate / 10000;
         int ExpireMonth = ExpireDate % 10000 / 100;
         int ExpireDay = ExpireDate % 100;
         if ( TDateTime::CurrentDate() >
              TDateTime(ExpireYear, ExpireMonth, ExpireDay) )
         {
            h_g::ShowMessage(UTF8String(h_g::I18nString("h_g:TRIAL_EXPIRED")));
            return;
         }
         ExpireDateStr.sprintf("%04d-%02d-%02d", ExpireYear,
            ExpireMonth, ExpireDay);
      }
      else
      {
         ExpireDateStr = UTF8String(h_g::I18nString("h_g:NO_EXPIRATION"));
      }
      AboutForm->EditLicenseUser->Text = UTF8String(LicUser);
      AboutForm->EditLicenseQty->Text = LicQty;
      AboutForm->EditExpire->Text = ExpireDateStr;

      if ( LicProject == "" )
      {
         AboutForm->EditLicenseProject->Text = UTF8String(h_g::I18nString("h_g:ANY_PROJECT"));
      }
      else
      {
         AboutForm->EditLicenseProject->Text = UTF8String(LicProject);
      }
   }

   RegisterStage("JOB", new HStageJob);
   RegisterStage("CONNECTOR", new HStageConnector);
   RegisterStage("EXTERN_JOB", new HStageExternJob);
   RegisterStage("EVENT_FIRE", new HStageEventFire);
   RegisterStage("EVENT_WAIT", new HStageEventWait);
   RegisterStage("GROUP", new HStageGroup);
   RegisterStage("TIME", new HStageTime);
   RegisterStage("BATCH", new HStageBatch);

   ClientCodeSet = "UTF8";
   Cfg = Config.ForceGetChild("MONITOR");
   TmpStr = Cfg->GetValue("INTERVAL").c_str();
   Interval = TmpStr.ToIntDef(60);

   {
      UTF8String FileName;
      FileName = Cfg->GetValue("WHISTLE_FILE").c_str();
      if ( FileName != "" )
      {
         WhistleFile = BinDir + FileName;
      }
      FileName = Cfg->GetValue("END_SOUND_FILE").c_str();
      if ( FileName != "" )
      {
         EndSoundFile = BinDir + FileName;
      }
   }

   PortalColQty = StrToInt(Cfg->GetValue("COLUMN", "10").c_str());

   if ( Copyright )
   {
   }
   else
   {
      AboutForm->Label2->Caption = "";
      AboutForm->Label3->Caption = "";
      AboutForm->Label9->Caption = "";
      AboutForm->Label10->Caption = "";
   }

   MainformCaption = UTF8String(Cfg->GetValue("TITLE", "Simjie's SIM-BAT").c_str());
   MainForm->Caption = MainformCaption;
   MainForm->PageControl1->Visible = false;
   MainForm->RemoveAll();
   HPortal *Portal = new HPortal(MainForm);
   Portal->Parent = MainForm;
   Portal->Align = alClient;
   MainForm->Portal = Portal;

   UTF8String GotoIp;
   int GotoPort = -1;
   UTF8String GotoGroup;

   if ( ( ParamCount() == 3 || ParamCount() == 4 ) && ParamStr(1) == "-goto" )
   {
      GotoIp = ParamStr(2);
      GotoPort = ParamStr(3).ToIntDef(-1);
      if ( ParamCount() == 4 )
      {
         GotoGroup = ParamStr(4);
      }
      const char *s = GotoGroup.c_str();
      int Pos = 0;
      for ( ; s[Pos] != '\0' && s[Pos] != ':'; Pos++ )
         ;
      GotoGroup.SetLength(Pos);
      GotoGroup = GotoGroup.UpperCase();
   }

   Portal->Init(PortalColQty, &Config, GotoIp, GotoPort, GotoGroup);
   Portal->PopupMenu = MainForm->PopupMenu2;
   ListForm->Clear();
   BatListForm->Clear();
   MainForm->ProgressBar = new HProgressBar(MainForm);
   MainForm->ProgressBar->Width = 150;
   MainForm->ProgressBar->Left = 410;
   MainForm->ProgressBar->Rate = 30;
   MainForm->ProgressBar->ShowFlag = false;
   MainForm->ProgressBar->Parent = MainForm->ToolBar1;

#ifdef SIMBAT_ENTERPRISE
   AboutForm->LabelEdition->Caption = UTF8String(I18nString("h_g:ENTERPRISE_EDITION"));
#else
   AboutForm->LabelEdition->Caption = UTF8String(I18nString("h_g:COMMUNITY_EDITION"));
#endif

   GanttForm->Init();
   ConcurrencyForm->Init();

   InitFail = false;
}

void __fastcall Close(void)
{
   for( map<UTF8String, HStage *>::iterator Iter = FStageRegister.begin();
        Iter != FStageRegister.end(); ++Iter )
      delete Iter->second;

   if ( LoadDavinciFlag )
   {
      SaveDavinciCode();
   }

   if ( InitFail )
      return;

   HXmlTree Config;

   if ( Config.LoadFromFile((BinDir + "simbat.cfg").c_str()) )
   {
      HXmlTree *Cfg = Config.ForceGetChild("MONITOR");
      vector<string> OldExcludeList;
      Cfg->GetValues("EXCLUDE_LIST", OldExcludeList);
      if ( OldExcludeList != ExcludeList )
      {
         Cfg->SetValues("EXCLUDE_LIST", ExcludeList);
         Config.SaveToFile((BinDir + "simbat.cfg").c_str());
      }
   }
   
   FreeSkin();
}

void __fastcall RegisterStage(const UTF8String &Type, HStage *Prototype)
{
   FStageRegister[Type] = Prototype;
}

HStage * __fastcall CloneStage(const UTF8String &Type)
{
   return FStageRegister[Type]->Clone();
}


void __fastcall ChangeSkin(const UTF8String &Skin)
{
   FreeSkin();
   LoadSkin(Skin);
   MainForm->RefreshCaption();
   HXmlTree Config;
   UTF8String TmpStr;

   if ( Config.LoadFromFile((BinDir + "simbat.cfg").c_str()) )
   {
      HXmlTree *Cfg = Config.ForceGetChild("COMMON");
      Cfg->SetValue("SKIN", Skin.c_str());
      Config.SaveToFile((BinDir + "simbat.cfg").c_str());
   }
}

void Davinci(void *Parm, int ParmLen)
{
   const int MASK_C = 0x01;
   const int MASK_S = 0x02;
   const int MASK_Z = 0x04;
   static char ByteOrWord[48]={
      0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
      0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
      0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x20,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   };

   unsigned int Pc = 0x0200;
   unsigned int Op1, Op2, Op3;
   unsigned char *Mem = DavinciCode;
   unsigned int Flags = 0;
   unsigned int StackP = 0;
   unsigned char Stack[2048];
   unsigned int i;

   memcpy(Mem, Parm, ParmLen);

   for ( ; ; )
   {
      unsigned char Code = Mem[Pc++];
      unsigned char Bow;
      if ( ( Code & 0xe0 ) == 0x20 )
      {
         Bow = ByteOrWord[Code & 0x0f];
      }
      if ( ( Code & 0xc0 ) == 0x40 )
      {
         Bow = ByteOrWord[(Code & 0x0f) + 16];
      }
      if ( ( Code & 0x80 ) == 0x80 )
      {
         Bow = ByteOrWord[(Code & 0x0f) + 32];
      }
      if ( ( Code & 0xe0 ) != 0x00 )
      {
         Op1 = Mem[Pc++];
         if ( ( Code & 0x10 ) || ( Bow & 0x10 ) )
         {
            Op1 = Op1 + Mem[Pc++] * 256;
         }
         if ( Code & 0x10 )
         {
            if ( Bow & 0x10 )
            {
               Op1 = Mem[Op1] + Mem[Op1 + 1] * 256;
            }
            else
            {
               Op1 = Mem[Op1];
            }
         }
         Code &= ~0x10;
      }
      if ( ( Code & 0xc0 ) != 0x00 )
      {
         Op2 = Mem[Pc++];
         if ( ( Code & 0x20 ) || ( Bow & 0x20 ) )
         {
            Op2 = Op2 + Mem[Pc++] * 256;
         }
         if ( Code & 0x20 )
         {
            if ( Bow & 0x20 )
            {
               Op2 = Mem[Op2] + Mem[Op2 + 1] * 256;
            }
            else
            {
               Op2 = Mem[Op2];
            }
         }
         Code &= ~0x20;
      }
      if ( ( Code & 0x80 ) != 0x00 )
      {
         Op3 = Mem[Pc++];
         if ( ( Code & 0x40 ) || ( Bow & 0x40 ) )
         {
            Op3 = Op3 + Mem[Pc++] * 256;
         }
         if ( Code & 0x40 )
         {
            if ( Bow & 0x40 )
            {
               Op3 = Mem[Op3] + Mem[Op3 + 1] * 256;
            }
            else
            {
               Op3 = Mem[Op3];
            }
         }
         Code &= ~0x40;
      }
      switch(Code)
      {
      case 0x01 :
         if ( StackP == 0 )
         {
            goto end;
         }
         Pc = Stack[StackP - 1] * 256 + Stack[StackP - 2];
         StackP -= 2;
         break;
      case 0x02 :
         break;
      case 0x03 :
         Flags |= MASK_C;
         break;
      case 0x04 :
         Flags &= ~MASK_C;
         break;
      case 0x05 :
         Flags |= MASK_S;
         break;
      case 0x06 :
         Flags &= ~MASK_S;
         break;
      case 0x07 :
         Flags |= MASK_Z;
         break;
      case 0x08 :
         Flags &= ~MASK_Z;
         break;
      case 0x09 :
         Stack[StackP++] = Flags % 256;
         break;
      case 0x0a :
         Flags = Stack[--StackP];
         break;
      case 0x20 :
         Pc = Op1;
         break;
      case 0x21 :
         if ( ( Flags & MASK_C ) != 0 )
         {
            if ( Op1 >= 128 )
            {
               Pc = Pc + Op1 - 256;
            }
            else
            {
               Pc += Op1;
            }
         }
         break;
      case 0x22 :
         if ( ( Flags & MASK_C ) == 0 )
         {
            if ( Op1 >= 128 )
            {
               Pc = Pc + Op1 - 256;
            }
            else
            {
               Pc += Op1;
            }
         }
         break;
      case 0x23 :
         if ( ( Flags & MASK_S ) != 0 )
         {
            if ( Op1 >= 128 )
            {
               Pc = Pc + Op1 - 256;
            }
            else
            {
               Pc += Op1;
            }
         }
         break;
      case 0x24 :
         if ( ( Flags & MASK_S ) == 0 )
         {
            if ( Op1 >= 128 )
            {
               Pc = Pc + Op1 - 256;
            }
            else
            {
               Pc += Op1;
            }
         }
         break;
      case 0x25 :
         if ( ( Flags & MASK_Z ) != 0 )
         {
            if ( Op1 >= 128 )
            {
               Pc = Pc + Op1 - 256;
            }
            else
            {
               Pc += Op1;
            }
         }
         break;
      case 0x26 :
         if ( ( Flags & MASK_Z ) == 0 )
         {
            if ( Op1 >= 128 )
            {
               Pc = Pc + Op1 - 256;
            }
            else
            {
               Pc += Op1;
            }
         }
         break;
      case 0x27 :
         Stack[StackP++] = Mem[Op1];
         break;
      case 0x28 :
         Mem[Op1] = Stack[--StackP];
         break;
      case 0x29 :
         Stack[StackP++] = Pc % 256;
         Stack[StackP++] = Pc / 256;
         Pc = Op1;
         break;
      case 0x2a :
         if ( ( Flags & MASK_C ) == 0 )
         {
            if ( ( Mem[Op1] & 0x80 ) == 0 )
            {
               Flags &= ~MASK_C;
            }
            else
            {
               Flags |= MASK_C;
            }
            Mem[Op1] <<= 1;
         }
         else
         {
            if ( ( Mem[Op1] & 0x80 ) == 0 )
            {
               Flags &= ~MASK_C;
            }
            else
            {
               Flags |= MASK_C;
            }
            Mem[Op1] <<= 1;
            Mem[Op1] |= 0x01;
         }
         break;
      case 0x2b :
         if ( ( Flags & MASK_C ) == 0 )
         {
            if ( ( Mem[Op1] & 0x01 ) == 0 )
            {
               Flags &= ~MASK_C;
            }
            else
            {
               Flags |= MASK_C;
            }
            Mem[Op1] >>= 1;
         }
         else
         {
            if ( ( Mem[Op1] & 0x01 ) == 0 )
            {
               Flags &= ~MASK_C;
            }
            else
            {
               Flags |= MASK_C;
            }
            Mem[Op1] >>= 1;
            Mem[Op1] |= 0x80;
         }
         break;
      case 0x40 :
         Mem[Op1] = Op2;
         break;
      case 0x41 :
         if ( ( Flags & MASK_C ) == 0 )
         {
            i = Mem[Op1] + Op2;
         }
         else
         {
            i = Mem[Op1] + Op2 + 1;
         }
         if ( i >= 256 )
         {
            Mem[Op1] = i - 256;
            Flags |= MASK_C;
         }
         else
         {
            Mem[Op1] = i % 256;
            Flags &= ~MASK_C;
         }
         if ( ( Mem[Op1] & 0x80) != 0 )
         {
            Flags |= MASK_S;
         }
         else
         {
            Flags &= ~MASK_S;
         }
         if ( Mem[Op1] == 0 )
         {
            Flags |= MASK_Z;
         }
         else
         {
            Flags &= ~MASK_Z;
         }
         break;
      case 0x42 :
         if ( ( Flags & MASK_C ) == 0 )
         {
            i = Mem[Op1] + 256 - Op2;
         }
         else
         {
            i = Mem[Op1] + 256 - Op2 - 1;
         }
         if ( i < 256 )
         {
            Mem[Op1] = i;
            Flags |= MASK_C;
         }
         else
         {
            Mem[Op1] = i % 256;
            Flags &= ~MASK_C;
         }
         if ( ( Mem[Op1] & 0x80 ) != 0 )
         {
            Flags |= MASK_S;
         }
         else
         {
            Flags &= ~MASK_S;
         }
         if ( Mem[Op1] == 0 )
         {
            Flags |= MASK_Z;
         }
         else
         {
            Flags &= ~MASK_Z;
         }
         break;
      case 0x43 :
         Mem[Op1] &= Op2;
         if ( ( Mem[Op1] & 0x80 ) != 0 )
         {
            Flags |= MASK_S;
         }
         else
         {
            Flags &= ~MASK_S;
         }
         if ( Mem[Op1] == 0 )
         {
            Flags |= MASK_Z;
         }
         else
         {
            Flags &= ~MASK_Z;
         }
         break;
      case 0x44 :
         Mem[Op1] |= Op2;
         if ( ( Mem[Op1] & 0x80 ) != 0 )
         {
            Flags |= MASK_S;
         }
         else
         {
            Flags &= ~MASK_S;
         }
         if ( Mem[Op1] == 0 )
         {
            Flags |= MASK_Z;
         }
         else
         {
            Flags &= ~MASK_Z;
         }
         break;
      case 0x45 :
         Mem[Op1] ^= Op2;
         if ( ( Mem[Op1] & 0x80 ) != 0 )
         {
            Flags |= MASK_S;
         }
         else
         {
            Flags &= ~MASK_S;
         }
         if ( Mem[Op1] == 0 )
         {
            Flags |= MASK_Z;
         }
         else
         {
            Flags &= ~MASK_Z;
         }
         break;
      case 0x46 :
         i = Mem[Op1] + 256 - Op2;
         if ( i < 256 )
         {
            Flags |= MASK_C;
         }
         else
         {
            Flags &= ~MASK_C;
         }
         if ( ( i & 0x80 ) != 0 )
         {
            Flags |= MASK_S;
         }
         else
         {
            Flags &= ~MASK_S;
         }
         if ( i % 256 == 0 )
         {
            Flags |= MASK_Z;
         }
         else
         {
            Flags &= ~MASK_Z;
         }
         break;
      case 0x47 :
         {
            typedef void HExternFunc(void *);
            HExternFunc *ExternFunc;
            memcpy(&ExternFunc, Mem + 128 + sizeof(void*) * Op1,
               sizeof(void*));
            ExternFunc(Mem + Op2);
         }
         break;
      case 0x80 :
         memcpy(Mem + Op1, Mem + Op2, Op3);
         break;
      case 0x81 :
         {
            int r = memcmp(Mem + Op1, Mem + Op2, Op3);
            if ( r == 0 )
            {
               Flags |= MASK_Z;
            }
            else
            {
               Flags &= ~MASK_Z;
            }
            if ( r < 0 )
            {
               Flags |= MASK_C;
            }
            else
            {
               Flags &= ~MASK_C;
            }
         }
         break;
      }
   }

end :

   memcpy(Parm, Mem, ParmLen);
}

#pragma pack(push, 1)
struct HDavinciArg0
{
   Graphics::TCanvas *Canvas;
#if !defined(_WIN64)
   char filler1[4];
#endif
   Graphics::TBitmap *Bitmap;
#if !defined(_WIN64)
   char filler2[4];
#endif
   unsigned char Flag;
};
struct HDavinciArg1
{
   Graphics::TBitmap *Bitmap;
#if !defined(_WIN64)
   char filler1[4];
#endif
   unsigned char Sample[8];
};
struct HDavinciArg2
{
   HBatchIcon *Batch;
#if !defined(_WIN64)
   char filler1[4];
#endif
};
struct HDavinciArg3
{
   unsigned char Flag;
};
struct HDavinciArg4
{
   unsigned char From;
   unsigned char To;
};
struct HDavinciArg6
{
   char DateStr[8];
   char Flag;
};
#pragma pack(pop)

void __fastcall Outline(void *Batch)
{
#pragma pack(push, 1)
   struct
   {
      char Func;
      HBatchIcon *Batch;
#if !defined(_WIN64)
      char filler1[4];
#endif
   } Arg;
#pragma pack(pop)

   static bool ExpireFlag = false;

   if ( ExpireFlag )
   {
      return;
   }

   Arg.Func = 3;
   Arg.Batch = (HBatchIcon*)Batch;
   OutlineCs->Enter();
   Davinci(&Arg, sizeof(Arg));

   if ( ExpireDate != 0 )
   {
      int ExpireYear = ExpireDate / 10000;
      int ExpireMonth = ExpireDate % 10000 / 100;
      int ExpireDay = ExpireDate % 100;
      if ( TDateTime::CurrentDate() >
           TDateTime(ExpireYear, ExpireMonth, ExpireDay) )
      {
         ExpireFlag = true;
      }
   }

   OutlineCs->Leave();
}

void __fastcall DrawLogo(TCanvas *Canvas)
{
#pragma pack(push, 1)
   struct
   {
      char Func;
      TCanvas *Canvas;
#if !defined(_WIN64)
      char filler1[4];
#endif
   } Arg;
#pragma pack(pop)
   Arg.Func = 1;
   Arg.Canvas = Canvas;
   Davinci(&Arg, sizeof(Arg));
}

void DavinciFunc0(HDavinciArg0 *Arg)
{
   Arg->Canvas->Draw(0, 0, Arg->Bitmap);

   if ( Arg->Flag != 1 )
   {
      Arg->Canvas->Pixels[2 + 2][2 + 2] = clBlack;
      Arg->Canvas->Pixels[2 + 1][2 + 3] = clBlack;
      Arg->Canvas->Pixels[2 + 3][2 + 3] = clBlack;
      Arg->Canvas->Pixels[2 + 2][2 + 4] = clBlack;
   }
}

void DavinciFunc1(HDavinciArg1 *Arg)
{
   TCanvas *Canvas = Arg->Bitmap->Canvas;

   for ( int i = 0; i < 8; i++ )
   {
      unsigned int Red;
      unsigned int Green;
      unsigned int Blue;
      Red = Canvas->Pixels[i * 4][i * 4] & 0x000000ff;
      Green = ( Canvas->Pixels[i * 4][i * 4] & 0x0000ff00 ) >> 8;
      Blue = ( Canvas->Pixels[i * 4][i * 4] & 0x00ff0000 ) >> 16;
      Arg->Sample[i] = ( Red * 30 + Green * 59 + Blue * 11 ) / 100 % 256;
   }
}

void DavinciFunc2(HDavinciArg2 *Arg)
{
   HBatchIcon *Batch = Arg->Batch;
   OutlineCs->Leave();
   HServer::FuncOutline(Batch);
   OutlineCs->Enter();
}

void DavinciFunc3(HDavinciArg3 *Arg)
{
   unsigned short Hour, Min, Sec, MSec;

   TDateTime::CurrentTime().DecodeTime(&Hour, &Min, &Sec, &MSec);

   if ( Hour < 2 || Hour >= 6 )
   {
      Arg->Flag = 0;
   }
   else
   {
      Arg->Flag = 1;
   }
}

void DavinciFunc4(HDavinciArg4 *Arg)
{
   BitmapJobBg1[Arg->To] = BitmapJobBg1[Arg->From];
   BitmapJobBg2[Arg->To] = BitmapJobBg2[Arg->From];
   BitmapJobBg3[Arg->To] = BitmapJobBg3[Arg->From];
   BitmapExternJobBg1[Arg->To] = BitmapExternJobBg1[Arg->From];
   BitmapExternJobBg2[Arg->To] = BitmapExternJobBg2[Arg->From];
   BitmapExternJobBg3[Arg->To] = BitmapExternJobBg3[Arg->From];
   BitmapGroupBg1[Arg->To] = BitmapGroupBg1[Arg->From];
   BitmapGroupBg2[Arg->To] = BitmapGroupBg2[Arg->From];
   BitmapGroupBg3[Arg->To] = BitmapGroupBg3[Arg->From];
   BitmapFwBg[Arg->To] = BitmapFwBg[Arg->From];
   BitmapServerBg[Arg->To] = BitmapServerBg[Arg->From];
}

void DavinciFunc5(HDavinciArg3 *Arg)
{
   int i = random(1000);

   if ( i == 97 )
   {
      Arg->Flag = 1;
   }
   else
   {
      Arg->Flag = 0;
   }
}

void DavinciFunc6(HDavinciArg6 *Arg)
{
   int ExpireYear = UTF8String(Arg->DateStr, 4).ToIntDef(0);
   int ExpireMonth = UTF8String(Arg->DateStr + 4, 2).ToIntDef(0);
   int ExpireDay = UTF8String(Arg->DateStr + 4 + 2, 2).ToIntDef(0);

   if ( ExpireYear > 0 && ExpireMonth > 0 && ExpireDay > 0 &&
        TDateTime::CurrentDate() > TDateTime(ExpireYear, ExpireMonth, ExpireDay) )
   {
      Arg->Flag = 1;
   }
   else
   {
      Arg->Flag = 0;
   }
}

static void __fastcall LoadDavinciCode(unsigned char *Buf)
{
   memcpy(DavinciCode, Buf, 1024);
   DecryptLic(DavinciCode);

   vector<void*> PtrVec;
   PtrVec.push_back((void*)&DavinciFunc0);
   PtrVec.push_back((void*)&DavinciFunc1);
   PtrVec.push_back((void*)&DavinciFunc2);
   PtrVec.push_back((void*)&DavinciFunc3);
   PtrVec.push_back((void*)&DavinciFunc4);
   PtrVec.push_back((void*)&DavinciFunc5);
   PtrVec.push_back((void*)&DavinciFunc6);
   memcpy(DavinciCode + 128, &PtrVec[0], sizeof(void*) * PtrVec.size());
#pragma pack(push, 1)
   struct
   {
      char Func;
      Graphics::TBitmap *Bitmap;
#if !defined(_WIN64)
      char filler1[4];
#endif
   } Arg;
#pragma pack(pop)
   Arg.Func = 0;
   Arg.Bitmap = DummyForm->ImageLogo->Picture->Bitmap;
   Davinci(&Arg, sizeof(Arg));
   LoadDavinciFlag = true;
}

static void __fastcall SaveDavinciCode()
{
   UTF8String LicFileName = BinDir + "simbat.lic";
   FILE *f = _wfopen(UnicodeString(LicFileName).c_str(), L"wb");

   if ( f != NULL )
   {
      unsigned char Buf[1024];
      memcpy(Buf, DavinciCode, 1024);
      EncryptLic(Buf);
      fwrite(Buf, 1024, 1, f);
      fclose(f);
   }
}

void __fastcall SetLogFileName(const UTF8String &FileName)
{
   LogFileName = FileName;
}

void WriteLog(const char *FormatStr, ...)
{
   DebugCs->Enter();

   if ( !DebugFlag )
   {
      DebugCs->Leave();
      return;
   }

   va_list      VaList;
   FILE         *f;
   time_t       t;
   struct tm    *tm;

   f = _wfopen(UnicodeString(LogFileName).c_str(), L"at");

   if ( f == NULL )
   {
      DebugCs->Leave();
      return;
   }

   t = time(NULL);
   tm = localtime(&t);
   fprintf(f, "%04d/%02d/%02d %02d:%02d:%02d  ",
      1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday,
      tm->tm_hour, tm->tm_min, tm->tm_sec);
   va_start(VaList, FormatStr);
   vfprintf(f, FormatStr, VaList);
   va_end(VaList);
   fprintf(f, "\n");
   fclose(f);
   DebugCs->Leave();
}

void __fastcall GetExcludeList(set<UTF8String> &StrSet)
{
   StrSet.clear();

   for ( int i = 0; i < ExcludeList.size(); i++ )
   {
      StrSet.insert(ExcludeList[i].c_str());
   }
}

void __fastcall SetExcludeList(const set<UTF8String> &StrSet)
{
   ExcludeList.clear();

   for ( set<UTF8String>::const_iterator Iter = StrSet.begin();
         Iter != StrSet.end(); Iter++ )
   {
      ExcludeList.push_back(Iter->c_str());
   }
}

void __fastcall ShowMessage(const UTF8String &Msg)
{
   MessageForm->ShowMessage(Msg);
}

} // end of namespace h_g
#pragma package(smart_init)
